Codebase list golang-github-vbauerster-mpb / ae77685
Move decorators to decor package Vladimir Bauer 9 years ago
5 changed file(s) with 276 addition(s) and 85 deletion(s). Raw diff Collapse all Expand all
66 "sync"
77 "time"
88 "unicode/utf8"
9
10 "github.com/vbauerster/mpb/decor"
911 )
1012
1113 const (
3739 state state
3840 }
3941
40 // Statistics represents statistics of the progress bar.
41 // Cantains: Total, Current, TimeElapsed, TimePerItemEstimate
42 type Statistics struct {
43 ID int
44 Completed bool
45 Aborted bool
46 Total int
47 Current int
48 StartTime time.Time
49 TimeElapsed time.Duration
50 TimePerItemEstimate time.Duration
51 }
52
5342 // Refil is a struct for b.IncrWithReFill
5443 type refill struct {
5544 char rune
5645 till int
57 }
58
59 // Eta returns exponential-weighted-moving-average ETA estimator
60 func (s *Statistics) Eta() time.Duration {
61 return time.Duration(s.Total-s.Current) * s.TimePerItemEstimate
6246 }
6347
6448 type (
8165 timeElapsed time.Duration
8266 blockStartTime time.Time
8367 timePerItem time.Duration
84 appendFuncs []DecoratorFunc
85 prependFuncs []DecoratorFunc
68 appendFuncs []decor.DecoratorFunc
69 prependFuncs []decor.DecoratorFunc
8670 simpleSpinner func() byte
8771 refill *refill
88 // flushed chan struct{}
8972 }
9073 )
9174
205188 }
206189 }
207190
208 // Statistics returs *Statistics, which contains information like
209 // Tottal, Current, TimeElapsed and TimePerItemEstimate
210 func (b *Bar) Statistics() *Statistics {
211 result := make(chan *Statistics, 1)
212 select {
213 case b.ops <- func(s *state) { result <- newStatistics(s) }:
214 return <-result
215 case <-b.done:
216 return newStatistics(&b.state)
217 }
218 }
219
220 // GetID returs id of the bar
221 func (b *Bar) GetID() int {
191 // ID returs id of the bar
192 func (b *Bar) ID() int {
222193 result := make(chan int, 1)
223194 select {
224195 case b.ops <- func(s *state) { result <- s.id }:
246217 func (b *Bar) Complete() {
247218 select {
248219 case <-b.completeReqCh:
249 return
250220 default:
251221 close(b.completeReqCh)
252222 }
253223 }
254224
225 func (b *Bar) complete() {
226 select {
227 case b.ops <- func(s *state) {
228 if !s.completed {
229 b.Complete()
230 }
231 }:
232 default:
233 }
234 }
235
255236 func (b *Bar) server(s state, wg *sync.WaitGroup, cancel <-chan struct{}) {
256237
257238 defer func() {
258239 b.state = s
259 // <-s.flushed
260 // fmt.Fprintf(os.Stderr, "Bar:%d flushed\n", s.id)
240 close(b.done)
261241 wg.Done()
262 close(b.done)
263242 }()
264243
265244 for {
276255 }
277256 }
278257 }
279
280 // func (b *Bar) render(tw int, flushed chan struct{}, prependWs, appendWs *widthSync) <-chan []byte {
281 // ch := make(chan []byte)
282
283 // go func() {
284 // defer func() {
285 // // recovering if external decorators panic
286 // if p := recover(); p != nil {
287 // ch <- []byte(fmt.Sprintln(p))
288 // }
289 // close(ch)
290 // }()
291 // result := make(chan []byte, 1)
292 // select {
293 // case b.ops <- func(s *state) {
294 // buf := draw(s, tw, prependWs, appendWs)
295 // buf = append(buf, '\n')
296 // result <- buf
297 // // wait for flushed
298 // if s.completed {
299 // <-flushed
300 // b.Complete()
301 // }
302 // }:
303 // ch <- <-result
304 // case <-b.done:
305 // buf := draw(&b.state, tw, prependWs, appendWs)
306 // buf = append(buf, '\n')
307 // ch <- buf
308 // default:
309 // ch <- []byte{}
310 // }
311 // }()
312
313 // return ch
314 // }
315258
316259 func (b *Bar) render(tw int, flushed chan struct{}, prependWs, appendWs *widthSync) <-chan []byte {
317260 ch := make(chan []byte)
472415 return buf
473416 }
474417
475 func newStatistics(s *state) *Statistics {
476 return &Statistics{
418 func newStatistics(s *state) *decor.Statistics {
419 return &decor.Statistics{
477420 ID: s.id,
478421 Completed: s.completed,
479422 Aborted: s.aborted,
0 package decor
1
2 import (
3 "fmt"
4 "math"
5 "time"
6 "unicode/utf8"
7 )
8
9 const (
10 // DidentRight specifies identation direction.
11 // | foo| b| Without DidentRight
12 // |foo |b | With DidentRight
13 DidentRight = 1 << iota
14
15 // DwidthSync will auto sync max width
16 DwidthSync
17
18 // DextraSpace adds extra space, makes sence with DwidthSync only.
19 // When DidentRight bit set, the space will be added to the right,
20 // otherwise to the left.
21 DextraSpace
22 )
23
24 // Statistics represents statistics of the progress bar.
25 // Cantains: Total, Current, TimeElapsed, TimePerItemEstimate
26 type Statistics struct {
27 ID int
28 Completed bool
29 Aborted bool
30 Total int
31 Current int
32 StartTime time.Time
33 TimeElapsed time.Duration
34 TimePerItemEstimate time.Duration
35 }
36
37 // Eta returns exponential-weighted-moving-average ETA estimator
38 func (s *Statistics) Eta() time.Duration {
39 return time.Duration(s.Total-s.Current) * s.TimePerItemEstimate
40 }
41
42 // DecoratorFunc is a function that can be prepended and appended to the progress bar
43 type DecoratorFunc func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string
44
45 func Name(name string, minWidth int, conf byte) DecoratorFunc {
46 format := "%%"
47 if (conf & DidentRight) != 0 {
48 format += "-"
49 }
50 format += "%ds"
51 return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
52 if (conf & DwidthSync) != 0 {
53 myWidth <- utf8.RuneCountInString(name)
54 max := <-maxWidth
55 if (conf & DextraSpace) != 0 {
56 max++
57 }
58 return fmt.Sprintf(fmt.Sprintf(format, max), name)
59 }
60 return fmt.Sprintf(fmt.Sprintf(format, minWidth), name)
61 }
62 }
63
64 func Counters(pairFormat string, unit Units, minWidth int, conf byte) DecoratorFunc {
65 format := "%%"
66 if (conf & DidentRight) != 0 {
67 format += "-"
68 }
69 format += "%ds"
70 return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
71 current := Format(s.Current).To(unit)
72 total := Format(s.Total).To(unit)
73 str := fmt.Sprintf(pairFormat, current, total)
74 if (conf & DwidthSync) != 0 {
75 myWidth <- utf8.RuneCountInString(str)
76 max := <-maxWidth
77 if (conf & DextraSpace) != 0 {
78 max++
79 }
80 return fmt.Sprintf(fmt.Sprintf(format, max), str)
81 }
82 return fmt.Sprintf(fmt.Sprintf(format, minWidth), str)
83 }
84 }
85
86 func ETA(minWidth int, conf byte) DecoratorFunc {
87 format := "%%"
88 if (conf & DidentRight) != 0 {
89 format += "-"
90 }
91 format += "%ds"
92 return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
93 str := fmt.Sprint(time.Duration(s.Eta().Seconds()) * time.Second)
94 if (conf & DwidthSync) != 0 {
95 myWidth <- utf8.RuneCountInString(str)
96 max := <-maxWidth
97 if (conf & DextraSpace) != 0 {
98 max++
99 }
100 return fmt.Sprintf(fmt.Sprintf(format, max), str)
101 }
102 return fmt.Sprintf(fmt.Sprintf(format, minWidth), str)
103 }
104 }
105
106 func Elapsed(minWidth int, conf byte) DecoratorFunc {
107 format := "%%"
108 if (conf & DidentRight) != 0 {
109 format += "-"
110 }
111 format += "%ds"
112 return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
113 str := fmt.Sprint(time.Duration(s.TimeElapsed.Seconds()) * time.Second)
114 if (conf & DwidthSync) != 0 {
115 myWidth <- utf8.RuneCountInString(str)
116 max := <-maxWidth
117 if (conf & DextraSpace) != 0 {
118 max++
119 }
120 return fmt.Sprintf(fmt.Sprintf(format, max), str)
121 }
122 return fmt.Sprintf(fmt.Sprintf(format, minWidth), str)
123 }
124 }
125
126 func Percentage(minWidth int, conf byte) DecoratorFunc {
127 format := "%%"
128 if (conf & DidentRight) != 0 {
129 format += "-"
130 }
131 format += "%ds"
132 return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
133 str := fmt.Sprintf("%d %%", percentage(s.Total, s.Current, 100))
134 if (conf & DwidthSync) != 0 {
135 myWidth <- utf8.RuneCountInString(str)
136 max := <-maxWidth
137 if (conf & DextraSpace) != 0 {
138 max++
139 }
140 return fmt.Sprintf(fmt.Sprintf(format, max), str)
141 }
142 return fmt.Sprintf(fmt.Sprintf(format, minWidth), str)
143 }
144 }
145
146 func percentage(total, current, ratio int) int {
147 if total == 0 || current > total {
148 return 0
149 }
150 num := float64(ratio) * float64(current) / float64(total)
151 ceil := math.Ceil(num)
152 diff := ceil - num
153 // num = 2.34 will return 2
154 // num = 2.44 will return 3
155 if math.Max(diff, 0.6) == diff {
156 return int(num)
157 }
158 return int(ceil)
159 }
0 package decor
1
2 import "fmt"
3
4 const (
5 _ = iota
6 bytesInKiB = 1 << (iota * 10)
7 bytesInMiB
8 bytesInGiB
9 bytesInTiB
10 )
11
12 const (
13 bytesInKb = 1000
14 bytesInMB = bytesInKb * 1000
15 bytesInGB = bytesInMB * 1000
16 bytesInTB = bytesInGB * 1000
17 )
18
19 const (
20 // Kibibyte = 1024 b
21 Unit_KiB = iota
22 // Kilobyte = 1000 b
23 Unit_kB
24 )
25
26 type Units uint
27
28 func Format(i int) *formatter {
29 return &formatter{n: i}
30 }
31
32 type formatter struct {
33 n int
34 unit Units
35 width int
36 }
37
38 func (f *formatter) To(unit Units) *formatter {
39 f.unit = unit
40 return f
41 }
42
43 func (f *formatter) Width(width int) *formatter {
44 f.width = width
45 return f
46 }
47
48 func (f *formatter) String() string {
49 switch f.unit {
50 case Unit_KiB:
51 return formatKiB(f.n)
52 case Unit_kB:
53 return formatKB(f.n)
54 default:
55 return fmt.Sprintf(fmt.Sprintf("%%%dd", f.width), f.n)
56 }
57 }
58
59 func formatKiB(i int) (result string) {
60 switch {
61 case i >= bytesInTiB:
62 result = fmt.Sprintf("%.1fTiB", float64(i)/bytesInTiB)
63 case i >= bytesInGiB:
64 result = fmt.Sprintf("%.1fGiB", float64(i)/bytesInGiB)
65 case i >= bytesInMiB:
66 result = fmt.Sprintf("%.1fMiB", float64(i)/bytesInMiB)
67 case i >= bytesInKiB:
68 result = fmt.Sprintf("%.1fKiB", float64(i)/bytesInKiB)
69 default:
70 result = fmt.Sprintf("%db", i)
71 }
72 return
73 }
74
75 func formatKB(i int) (result string) {
76 switch {
77 case i >= bytesInTB:
78 result = fmt.Sprintf("%.1fTB", float64(i)/bytesInTB)
79 case i >= bytesInGB:
80 result = fmt.Sprintf("%.1fGB", float64(i)/bytesInGB)
81 case i >= bytesInMB:
82 result = fmt.Sprintf("%.1fMB", float64(i)/bytesInMB)
83 case i >= bytesInKb:
84 result = fmt.Sprintf("%.1fkB", float64(i)/bytesInKb)
85 default:
86 result = fmt.Sprintf("%db", i)
87 }
88 return
89 }
66 "time"
77
88 "github.com/vbauerster/mpb"
9 "github.com/vbauerster/mpb/decor"
910 )
1011
1112 const (
2627 if i != 1 {
2728 name = fmt.Sprintf("Bar#%d:", i)
2829 }
29 b := p.AddBar(int64(total),
30 b := p.AddBar(total,
3031 mpb.PrependDecorators(
31 mpb.Name(name, 0, mpb.DwidthSync|mpb.DidentRight),
32 mpb.ETA(4, mpb.DwidthSync|mpb.DextraSpace),
32 decor.Name(name, 0, decor.DwidthSync|decor.DidentRight),
33 decor.ETA(4, decor.DwidthSync|decor.DextraSpace),
3334 ),
3435 mpb.AppendDecorators(
35 mpb.Percentage(5, 0),
36 decor.Percentage(5, 0),
3637 ),
3738 )
3839 go func() {
149149 // complete Total unknown bars
150150 p.ops <- func(c *pConf) {
151151 for _, b := range c.bars {
152 s := b.Statistics()
153 if !s.Completed && !s.Aborted {
154 b.Complete()
155 }
152 b.complete()
156153 }
157154 }
158155 // wait for all bars to quit